/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.kurvykurvy.core.ui;

import com.kurvykurvy.image.ImageFrameWidget;
import com.kurvykurvy.image.LoadedImage;
import com.kurvykurvy.page.ImageFrame;
import com.kurvykurvy.page.PageLayoutTemplate;
import com.kurvykurvy.page.PageSpread;
import com.kurvykurvy.visuals.PageLayoutScene;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Iterator;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.TransferHandler;
import org.netbeans.api.visual.action.ConnectorState;
import org.netbeans.api.visual.widget.Widget;
import org.openide.util.NbBundle;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
//import org.openide.util.ImageUtilities;
import org.netbeans.api.settings.ConvertAsProperties;
import org.netbeans.api.visual.action.AcceptProvider;
import org.netbeans.api.visual.action.ActionFactory;
import org.netbeans.api.visual.widget.ImageWidget;
import org.netbeans.api.visual.widget.Scene;
import org.openide.util.Exceptions;

/**
 * Top component which displays something.
 */
@ConvertAsProperties( dtd = "-//com.kurvykurvy.core.ui//NewKurvyLayoutEditor//EN",
autostore = false )
public final class NewKurvyLayoutEditorTopComponent
        extends TopComponent
        implements DropTargetListener
{

    private static NewKurvyLayoutEditorTopComponent instance;
    /** path to the icon used by the component and its open action */
//    static final String ICON_PATH = "SET/PATH/TO/ICON/HERE";
    private static final String PREFERRED_ID = "NewKurvyLayoutEditorTopComponent";
    protected Scene layout;
    protected JComponent layoutView;
    protected PageSpread pageSpread;
    protected BufferedImage pageSpreadMask;

    public NewKurvyLayoutEditorTopComponent()
    {
        initComponents();
        setName( NbBundle.getMessage( NewKurvyLayoutEditorTopComponent.class, "CTL_NewKurvyLayoutEditorTopComponent" ) );
        setToolTipText( NbBundle.getMessage( NewKurvyLayoutEditorTopComponent.class, "HINT_NewKurvyLayoutEditorTopComponent" ) );
//        setIcon(ImageUtilities.loadImage(ICON_PATH, true));

        layout = new PageLayoutScene();
        layout.getActions().addAction( ActionFactory.createZoomAction() );
        layout.setBackground( Color.DARK_GRAY );
        layout.setZoomFactor( 0.5 );
        layoutView = layout.createView();
        layoutViewPane.setViewportView( layoutView );
        layoutViewPane.getViewport().setViewPosition( new Point( -100, 100 ) );
    }

    public void renderScene()
    {
        layout.removeChildren();

        if ( pageSpread.getImageFrames() != null && !pageSpread.getImageFrames().isEmpty() )
        {
            for ( Iterator<ImageFrame> it = pageSpread.getImageFrames().iterator(); it.hasNext(); )
            {
                ImageFrame frame = it.next();
                ImageFrameWidget widget = new ImageFrameWidget( layout, frame );
                widget.setBorder( javax.swing.BorderFactory.createLineBorder( Color.BLUE ) );
//                widget.getActions().addAction( ActionFactory.createMoveAction() );
                widget.getActions().addAction(  ActionFactory.createZoomAction() );
                widget.getActions().addAction(
                        ActionFactory.createAcceptAction(
                        new AcceptProvider()
                        {

                            public ConnectorState isAcceptable( Widget widget, Point pt, Transferable transferable )
                            {
                                if ( widget instanceof ImageFrameWidget )
                                {
                                    try
                                    {
                                        if ( transferable.getTransferData( LoadedImage.LOADED_IMAGE_DATA_FLAVOR ) instanceof LoadedImage )
                                        {
                                            System.out.println( "Acceptable" );
                                            accept( widget, pt, transferable );
                                            return ConnectorState.ACCEPT;
                                        }
                                    }
                                    catch ( UnsupportedFlavorException unsupportedFlavor )
                                    {
                                    }
                                    catch ( IOException ioEx )
                                    {
                                    }
                                }
                                return ConnectorState.REJECT;
                            }

                            public void accept( Widget widget, Point pt, Transferable transferable )
                            {
                                System.out.println( "Accept" );
                                if ( widget instanceof ImageFrameWidget )
                                {
                                    try
                                    {
                                        if ( transferable.getTransferData( LoadedImage.LOADED_IMAGE_DATA_FLAVOR ) instanceof LoadedImage )
                                        {
                                            ((ImageFrameWidget) widget).setImage( (LoadedImage) transferable.getTransferData( LoadedImage.LOADED_IMAGE_DATA_FLAVOR ) );
                                        }
                                    }
                                    catch ( UnsupportedFlavorException unsupportedFlavorEx )
                                    {
                                    }
                                    catch ( IOException ioEx )
                                    {
                                    }
                                }
                            }
                        } ) );
//                widget.bringToFront();
                layout.addChild( widget );
            }
        }

        PageLayoutTemplate template = null;
        int xOffset = 0;
        if ( this.pageSpread.getPageLayoutTemplate( PageSpread.LEFT_SPREAD_PAGE ) != null )
        {
            template = this.pageSpread.getPageLayoutTemplate( PageSpread.LEFT_SPREAD_PAGE );
            ImageWidget decor = new ImageWidget( layout );
            decor.setImage( template.getTemplateDecorations() );
            decor.setPreferredLocation( new Point( xOffset, 0 ) );
            decor.bringToFront();
            layout.addChild( decor );
            xOffset += template.getTemplateDecorations().getWidth();
        }

        if ( this.pageSpread.getPageLayoutTemplate( PageSpread.RIGHT_SPREAD_PAGE ) != null )
        {
            template = this.pageSpread.getPageLayoutTemplate( PageSpread.RIGHT_SPREAD_PAGE );
            ImageWidget decor = new ImageWidget( layout );
            decor.setPreferredLocation( new Point( xOffset, 0 ) );
            decor.setImage( template.getTemplateDecorations() );
            decor.bringToFront();
            layout.addChild( decor );
        }

        layout.validate();
    }

    public void setPageTemplate( PageLayoutTemplate template )
    {
        this.pageSpread.setPageLayoutTemplate( template );
    }

    public void setPageSpread( PageSpread spread )
    {
        this.pageSpread = spread;
        renderScene();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        layoutViewPane = new javax.swing.JScrollPane();

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(layoutViewPane, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(layoutViewPane, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane layoutViewPane;
    // End of variables declaration//GEN-END:variables

    /**
     * Gets default instance. Do not use directly: reserved for *.settings files only,
     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
     * To obtain the singleton instance, use {@link #findInstance}.
     */
    public static synchronized NewKurvyLayoutEditorTopComponent getDefault()
    {
        if ( instance == null )
        {
            instance = new NewKurvyLayoutEditorTopComponent();
        }
        return instance;
    }

    /**
     * Obtain the NewKurvyLayoutEditorTopComponent instance. Never call {@link #getDefault} directly!
     */
    public static synchronized NewKurvyLayoutEditorTopComponent findInstance()
    {
        TopComponent win = WindowManager.getDefault().findTopComponent( PREFERRED_ID );
        if ( win == null )
        {
            Logger.getLogger( NewKurvyLayoutEditorTopComponent.class.getName() ).warning(
                    "Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system." );
            return getDefault();
        }
        if ( win instanceof NewKurvyLayoutEditorTopComponent )
        {
            return (NewKurvyLayoutEditorTopComponent) win;
        }
        Logger.getLogger( NewKurvyLayoutEditorTopComponent.class.getName() ).warning(
                "There seem to be multiple components with the '" + PREFERRED_ID +
                "' ID. That is a potential source of errors and unexpected behavior." );
        return getDefault();
    }

    @Override
    public int getPersistenceType()
    {
        return TopComponent.PERSISTENCE_ALWAYS;
    }

    @Override
    public void componentOpened()
    {
        // TODO add custom code on component opening
    }

    @Override
    public void componentClosed()
    {
        // TODO add custom code on component closing
    }

    void writeProperties( java.util.Properties p )
    {
        // better to version settings since initial version as advocated at
        // http://wiki.apidesign.org/wiki/PropertyFiles
        p.setProperty( "version", "1.0" );
        // TODO store your settings
    }

    Object readProperties( java.util.Properties p )
    {
        NewKurvyLayoutEditorTopComponent singleton = NewKurvyLayoutEditorTopComponent.getDefault();
        singleton.readPropertiesImpl( p );
        return singleton;
    }

    private void readPropertiesImpl( java.util.Properties p )
    {
        String version = p.getProperty( "version" );
        // TODO read your settings according to their version
    }

    @Override
    protected String preferredID()
    {
        return PREFERRED_ID;
    }

    public void dragEnter( DropTargetDragEvent dtde )
    {
        Transferable transferData = dtde.getTransferable();
        if ( transferData instanceof PageLayoutTemplate ||
                transferData instanceof PageSpread )
        {
            dtde.acceptDrag( TransferHandler.COPY );
            System.out.println( "Drag Entered" );
        }
    }

    public void dragOver( DropTargetDragEvent dtde )
    {
        Transferable transferData = dtde.getTransferable();
        if ( transferData instanceof PageLayoutTemplate ||
                transferData instanceof PageSpread )
        {
            dtde.acceptDrag( TransferHandler.COPY );
            System.out.println( "Drag Overed" );
        }
    }

    public void dropActionChanged( DropTargetDragEvent dtde )
    {
    }

    public void dragExit( DropTargetEvent dte )
    {
    }

    public void drop( DropTargetDropEvent dtde )
    {
        System.out.println( "Drop?" );
        try
        {
            Transferable transferable = dtde.getTransferable();

            DataFlavor[] flavors = dtde.getCurrentDataFlavors();
            for ( int i = 0; i < flavors.length; i++ )
            {
                Object transferData = transferable.getTransferData( flavors[i] );
                if ( transferData instanceof PageLayoutTemplate )
                {
                    dtde.acceptDrop( DnDConstants.ACTION_COPY );
                    this.pageSpread.setPageLayoutTemplate( (PageLayoutTemplate) transferData );
                    System.out.println( "DROP!!" );
                    this.renderScene();
                    this.updateUI();
                    dtde.dropComplete( true );
                }
                else if ( transferData instanceof PageSpread )
                {
                    dtde.acceptDrop( DnDConstants.ACTION_COPY );
                    System.out.println( "New DROP!!" );
                    System.out.println( "New Page Spread : " + transferData );
                    setPageSpread( (PageSpread) transferData );
                    this.renderScene();
                    this.updateUI();
                    dtde.dropComplete( true );
                }
            }
        }
        catch ( UnsupportedFlavorException ex )
        {
            Exceptions.printStackTrace( ex );
        }
        catch ( IOException ex )
        {
            Exceptions.printStackTrace( ex );
        }
    }

    @Override
    public void setSize( Dimension d )
    {
        super.setSize( d );
    }
}
